package com.aatattoo.light_food_service.filter;


import com.aatattoo.light_food_service.config.error.ResultData;
import com.aatattoo.light_food_service.entity.Token;
import com.aatattoo.light_food_service.service.TokenService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.*;


public class TokenInterceptor implements HandlerInterceptor {
    @Autowired
    private TokenService tokenService;
    //提供查询
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {}
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {}
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        //普通路径放行
        if (pass(arg0.getRequestURI())) {
            return true;
        }
        //权限路径拦截
        arg1.setCharacterEncoding("UTF-8");
//        Enumeration<String> headerNames = arg0.getHeaderNames();
//        while (headerNames.hasMoreElements()){
//            String name = headerNames.nextElement();
//            //根据名称获取请求头的值
//            String value = arg0.getHeader(name);
//            System.out.println(name+"---"+value);
//         }
        final String headerToken=arg0.getHeader("token");
//        System.out.println(headerToken);
        //判断请求信息
        if(null==headerToken||headerToken.trim().equals("")){
            PrintWriter resultWriter=arg1.getWriter();
            Map<String,Object> map = new HashMap<>();
            String result = result(403, "该账户没有token,需要登录", "");
            resultWriter.println(result);
            return false;
        }
        //解析Token信息
        try {
            Claims claims = Jwts.parser().setSigningKey("account").parseClaimsJws(headerToken).getBody();
            String tokenUserId=(String)claims.get("userid");
            int itokenUserId=Integer.parseInt(tokenUserId);
            //数据库没有Token记录
            if(tokenService.isTableExist(itokenUserId)==0) {
                PrintWriter resultWriter=arg1.getWriter();
                String result = result(403, "该账户没有token,需要登录", "");
                resultWriter.println(result);
                return false;
            }
            //根据客户Token查找数据库Token
            Token myToken=tokenService.findByUserId(itokenUserId);
            //数据库Token与客户Token比较
            if( !headerToken.equals(myToken.getToken()) ){
                PrintWriter resultWriter=arg1.getWriter();
                String result = result(403, "该账户token异常，需要登录", "");
                resultWriter.println(result);
                return false;
            }
            //判断Token过期
            Date tokenDate=(Date)claims.getExpiration();
            int chaoshi=(int)(System.currentTimeMillis()-tokenDate.getTime())/1000;
            if(chaoshi>60*60*24*3){
                PrintWriter resultWriter=arg1.getWriter();
                String result = result(401, "该账户token过期，重新登录", "");
                resultWriter.println(result);
                return false;
            }
        } catch (Exception e) {
            PrintWriter resultWriter=arg1.getWriter();
            e.printStackTrace();
            String result = result(403, "该账户token异常，需要登录", "");
            resultWriter.println(result);
            return false;
        }
        //最后才放行
        return true;
    }

    private String result(int code,String msg,String data) throws JsonProcessingException {
        ObjectMapper objectMapper=new ObjectMapper();
        ResultData resultData = new ResultData<>();
        resultData.setCode(code);
        resultData.setMessage(msg);
        resultData.setData(data);
        return objectMapper.writeValueAsString(resultData);
    }

    private boolean pass(String url){
        //可通过的url放在下面数组里
        String[] passUrl={"/user/register","/user/login","/upload/avatar",
        "/user/security","/user/answer","/user/password","/user/checkUser",
        "/sms/checkCode","/sms/register","/sms/forgetPassword"};
        return Arrays.asList(passUrl).contains(url);
    }
}
